
public class Test {
    public static void main(String[] args) throws Exception {
        Client.main();
    }
}

// 提供一个创建一系列相关或相互依赖对象的接口，而无需指定它们具体的类。
// 抽象工厂模式和工厂方法不太一样，它要解决的问题比较复杂，不但工厂是抽象的，产品是抽象的，而且有多个产品需要创建，因此，这个抽象工厂会对应到多个实际工厂，每个实际工厂负责创建多个实际产品

// 跨平台的 GUI 部件工厂——同样一套客户端代码，可以切换 Windows 或 Mac 风格
interface Button {
    void paint();
}

interface TextField {
    void paint();
}

// window风格
class WinButton implements Button {
    public void paint() {
        System.out.println("Render Windows button");
    }
}

class WinTextField implements TextField {
    public void paint() {
        System.out.println("Render Windows text field");
    }
}

// mac风格
class MacButton implements Button {
    public void paint() {
        System.out.println("Render Mac button");
    }
}

class MacTextField implements TextField {
    public void paint() {
        System.out.println("Render Mac text field");
    }
}

interface GUIFactory {
    Button createButton();

    TextField createTextField();
}

class WinFactory implements GUIFactory {
    public Button createButton() {
        return new WinButton();
    }

    public TextField createTextField() {
        return new WinTextField();
    }
}

class MacFactory implements GUIFactory {
    public Button createButton() {
        return new MacButton();
    }

    public TextField createTextField() {
        return new MacTextField();
    }
}

class Client {
    private Button btn;
    private TextField txt;

    // 运行时注入工厂即可
    public Client(GUIFactory factory) {
        btn = factory.createButton();
        txt = factory.createTextField();
    }

    public void render() {
        btn.paint();
        txt.paint();
    }

    public static void main() {
        // 通过配置或环境变量切换平台
        GUIFactory factory = System.getProperty("os.name").toLowerCase().contains("win")
                ? new WinFactory()
                : new MacFactory();

        new Client(factory).render();
    }
}